<?php
/**
 * This file is part of DomBankLink.
 * 
 * DomBankLink is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * DomBankLink is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with DomBankLink.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * @link http://inditel.ee/
 * @copyright 2007-2009 Inditel Meedia OÜ
 * @author Oliver Leisalu <oliver@inditel.ee>
 */

/**
 * 
 */
abstract class DomBankLink_SampoSebSwed extends DomBankLink {
	
	/**
	* Private key file path
	* @var String
	*/
	protected $privateKey;
	/**
	* Request/Public key file path
	* @var String
	*/
	protected $requestKey;
	/**
	* Reseller identification code
	* @var String
	*/
	protected $resellerId;
	/**
	* Account number
	* @var String
	*/
	protected $resellerAccount;
	/**
	* Account owner
	* @var String
	*/
	protected $resellerName;
	/**
	 * @var String
	 */
	protected $serverUrl;
	/**
	 * @var String
	 */
	protected $outputEncoding = 'ISO-8859-4';
	/**
	 * @var String
	 */
	protected $inputEncoding = 'UTF-8';
	/**
	 * @var String
	 */
	protected $lang = 'EST';
	

	public function sendToBank( DomBankLinkObject $payment ) {
		
		if( $payment instanceof DomBankPayment ) {
			$rsField = array(
				'VK_SERVICE'    => '1001',
				'VK_VERSION'    => '008',
				'VK_SND_ID'     => $this->resellerId,
				'VK_STAMP'      => $payment->id,
				'VK_AMOUNT'     => $payment->price,
				'VK_CURR'       => strtoupper($payment->currency),
				'VK_ACC'        => $this->resellerAccount,
				'VK_NAME'       => $this->resellerName,
				'VK_REF'        => $this->referenceNumber($payment->id),
				'VK_MSG'        => $payment->description,
				'VK_RETURN'     => $this->getCallBackUrl( $payment ),
				'VK_CANCEL'     => $this->getCallBackUrl( $payment ),
				'VK_LANG'		=> $this->lang,
				'VK_CHARSET'	=> $this->outputEncoding
			);
		} else if( $payment instanceof DomBankIdentify ) {
			$rsField = array(
				'VK_SERVICE'    => '4001',
				'VK_VERSION'    => '008',
				'VK_SND_ID'     => $this->resellerId,
				'VK_REPLY'      => 3002,
				'VK_RETURN'     => $this->getCallBackUrl( $payment ),
				'VK_DATE'		=> date('d.m.Y'),
				'VK_TIME'		=> date('H:i:s'),
			);
		}
        	
        $flKey = openssl_pkey_get_private(file_get_contents($this->privateKey));

		if (!openssl_sign($this->checkSum($rsField, $this->outputEncoding, $this->outputEncoding), $signature, $flKey)) {
			trigger_error ("Unable to generate signature", E_USER_ERROR);
		}

    	$rsField['VK_MAC'] = base64_encode($signature);
    	
		
    	$fields = '';
    	foreach ($rsField as $ixField => $fieldValue) {
    		$fields .= '<input type="hidden" name="' . $ixField . '" value="' . htmlspecialchars(iconv($this->inputEncoding, $this->outputEncoding, $fieldValue)) . '" />' . "\n";
    	}

    	$form = '
			<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
			<html xmlns="http://www.w3.org/1999/xhtml">
			<head>
			<meta http-equiv="Content-Type" content="text/html; charset='.$this->outputEncoding.'" />
			<title>Suunamine</title>
			</head>
			<body>
			<form id="form" action="'.$this->serverUrl.'" method="POST">
				'.$fields.'
				<input type="submit" value="Edasi panka"/>
			</form>
			<script type="text/javascript"> t = setTimeout( "document.getElementById(\"form\").submit()" ,500 ); </script>	
			</body>
			</html>';
    	
    	echo $form;
		die();
	}
	
	public function handleReplay( $paymentClassName, $requestId = NULL ) {
		
		$rsField = array();
		foreach ((array)$_REQUEST as $ixField => $fieldValue) {
			if ( substr($ixField, 0, 3) == 'VK_') {
				$rsField[$ixField] = $fieldValue;
	        }
		}
	   	
	    if( $rsField['VK_STAMP'] > 0 )
	    	$requestId = $rsField['VK_STAMP'];
		
	    $payment = DomAr::load( $requestId, $paymentClassName );
	    
	    if( !$payment )
			return false;
		
			
		if( $payment->status != DomBankPayment::SENT_TO_BANK )
			return $payment;

			
		if( !file_exists($this->requestKey) )
			throw new RuntimeException('Public key doesn\'t exist for profile <b>'.$payment->profile.'</b>' );
		
		
		// Invalid signature
		$flKey = openssl_pkey_get_public( file_get_contents($this->requestKey) );
		if ( !openssl_verify ( $this->checkSum($rsField, $this->outputEncoding, $this->outputEncoding), base64_decode($rsField['VK_MAC']), $flKey) ) {
			$payment->status = 3;
		
		// payment was cancelled
		} else if ($rsField['VK_SERVICE'] == "1901") {
			$payment->status = 2;
		
		// payment successful
		} else if ($rsField['VK_SERVICE'] == "1101" or $rsField['VK_SERVICE'] == "3002") {
			$payment->status = 1;
		
		// Other error
		} else {
			$payment->status = 3;
		}
		
		$payment->backTime = 'now';
		$payment->backIp = ip();
		if( $payment instanceof DomBankPayment ) {
			$payment->clientAccountNr = $rsField['VK_SND_ACC'];
			$payment->clientName = strtoupper($rsField['VK_SND_NAME']);
		}
		
		
		if( $payment instanceof DomBankIdentify ) {

			list($personCode, $name) = explode(';', $rsField['VK_INFO']);
			$personCode = array_pop(explode(':', $personCode ));
			list($firstName, $lastName) = explode(',', array_pop(explode(':', $name )));
			
			$payment->clientCode = $personCode;
			$payment->clientName =  strtoupper( trim($lastName).' '.trim($firstName) );
		}
		
		if( !$payment->save() ) {
			throw new RuntimeException( $payment->getValidationMessages('<br>') );
		}
		
		return $payment;
	}
		
	
	/**
	* @internal
	*/
	protected function referenceNumber($ixOrder) {
		# reference number calculation using the algorithm provided by Pankade liit
		$rsMultiplier = array (7, 3, 1);
		$ixCurrentMultiplier = 0;
		$sixOrder = (string) $ixOrder;
		for ($i = strlen($sixOrder)-1; $i >= 0; $i--)
		{
			$rsProduct[$i] = substr($sixOrder, $i, 1)*$rsMultiplier[$ixCurrentMultiplier];
			if ($ixCurrentMultiplier == 2)
			{
				$ixCurrentMultiplier = 0;
			}
			else
			{
				$ixCurrentMultiplier++;
			}
		}
		$sumProduct = 0;
		foreach ($rsProduct as $product)
		{
			$sumProduct += $product;
		}
		if ($sumProduct % 10 == 0)
		{
			$ixReference = 0;
		}
		else
		{
			$ixReference = 10 - ($sumProduct % 10);
		}
		return $sixOrder.$ixReference;
	}
	
	/**
	* @internal
	*/
	protected function checkSum($rsField, $nInputEncoding, $outputEncoding) {
		$rsKey = $this->rsKey($rsField['VK_SERVICE']);
		$checkSum = '';
		foreach ($rsKey as $ixField) {
			$fieldContents = iconv($nInputEncoding, $outputEncoding, $rsField[$ixField]);
			$checkSum .= str_pad(strlen($fieldContents), 3, '0', STR_PAD_LEFT) . $fieldContents;
		}
		return $checkSum;
	}

	/**
	* @internal
	*/
	protected function rsKey($ixService) {
		if ($ixService == 1001) {
			return array(
				'VK_SERVICE',
				'VK_VERSION',
				'VK_SND_ID',
				'VK_STAMP',
				'VK_AMOUNT',
				'VK_CURR',
				'VK_ACC',
				'VK_NAME',
				'VK_REF',
				'VK_MSG'
				);
		} else if ($ixService == 1101) {
			return array(
				'VK_SERVICE',
				'VK_VERSION',
				'VK_SND_ID',
				'VK_REC_ID',
				'VK_STAMP',
				'VK_T_NO',
				'VK_AMOUNT',
				'VK_CURR',
				'VK_REC_ACC',
				'VK_REC_NAME',
				'VK_SND_ACC',
				'VK_SND_NAME',
				'VK_REF',
				'VK_MSG',
				'VK_T_DATE'
				);
		} else if ($ixService == 1901) {
			return array(
				'VK_SERVICE',
				'VK_VERSION',
				'VK_SND_ID',
				'VK_REC_ID',
				'VK_STAMP',
				'VK_REF',
				'VK_MSG'
				);
		} else if ($ixService == 4001) {
			return array(
				'VK_SERVICE',
				'VK_VERSION',
				'VK_SND_ID',
				'VK_REPLY',
				'VK_RETURN',
				'VK_DATE',
				'VK_TIME'
				);
		} else if ($ixService == 3002) {
			return array(
				'VK_SERVICE',
				'VK_VERSION',
				'VK_USER',
				'VK_DATE',
				'VK_TIME',
				'VK_SND_ID',
				'VK_INFO'
				);
		}  else {
			return array();
		}
	}
}
?>